home *** CD-ROM | disk | FTP | other *** search
- #! /usr/bin/perl -w
- # $Id: cups-genppdconfig.in,v 1.13.8.1 2007/05/29 01:47:26 rlk Exp $
- # A user-friendly dialog-based wrapper for cups-genppd(8).
- # Copyright (C) 2002 Roger Leigh <rleigh@debian.org>
- #
- # This program is free software; you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation; either version 2, or (at your option)
- # any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software
- # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- use strict;
- use File::Basename;
- use File::Find;
- use File::Temp qw(tempfile unlink0);
- use IO::Handle;
- use Getopt::Std;
- use POSIX;
-
- sub init_data();
- sub init_defaults();
- sub main_menu();
- sub display_help;
- sub choose_printers;
- sub choose_languages;
- sub choose_location;
- sub create_ppds;
- sub create_dir($);
- sub dialog_read($$);
- sub dialog_read_list (\%\@$$);
-
- my $DIALOG = "/usr/bin/dialog"; # version of dialog to call
- my $BACKTITLE = "Gutenprint CUPS PPD creation"; # dialog screen title
- my %printers; # master list of printers
- my %languages; # master list of languages
- my @used_printers; # printer PPDs on system
- my @used_languages; # languages used on system
- my @chosen_printers = (); # chosen printers
- my @chosen_languages = (); # chosen languages
- my $version = "5.0";
- my $chosen_location = "/usr/share/cups/model/gutenprint/$version";
- # chosen PPD prefix
- my $silent = 0; # no dialog
-
-
- # Set chosen_location from command-line.
- our $opt_d;
- our $opt_u;
- getopts('d:u');
- if ($opt_d) {
- $chosen_location = create_dir($opt_d);
- }
-
- # Initialise everything
- init_data();
- init_defaults();
-
- # Run non-interactively if `-u' was specified.
- if ( $opt_u ) {
- $silent = 1;
- create_ppds;
- exit 0;
- }
-
- # Can we use dialog?
- die "dialog(1) is not available, but is required for interactive use."
- if ! -x $DIALOG;
-
- while (my $option = main_menu()) { # Display main menu and run selection
- if ($option eq "Help") {
- display_help();
- } elsif ($option eq "Printers") {
- choose_printers();
- } elsif ($option eq "Languages") {
- choose_languages();
- } elsif ($option eq "Directory") {
- choose_location();
- } elsif ($option eq "Create") {
- create_ppds();
- } elsif ($option eq "Exit") {
- exit 0;
- } else {
- die "Invalid menu option: $option";
- }
- }
-
- exit 0;
-
-
- #
- # init_data() - Populate master printer and language hashes.
- #
- sub init_data() {
- my $model;
- my $desc;
- my $lang;
- # Get printer drivers and descriptions, then store in a hash.
- open GENPPD, "cups-genppd.$version -M -v |" or die "can't fork cups-genppd.$version: $!";
- while (<GENPPD>) {
- ($model, $desc) = /([\w-]+)\W+(.*)/;
- chomp ($model);
- chomp ($desc);
- $printers{$model} = $desc;
- }
- close GENPPD or die "can't close cups-genppd.$version pipe: $!";
- # Get available languages, then store in hash.
- open GENPPD, "cups-genppd.$version -L |" or die "can't fork cups-genppd.$version: $!";
- while (<GENPPD>) {
- $lang = $_;
- chomp ($lang);
- $languages{$lang} = "(No description)";
- }
- $languages{"en"} = "US English";
- close GENPPD or die "can't close cups-genppd.$version pipe: $!";
- # Set defaults
- @chosen_languages = ("en");
- }
-
-
- #
- # init_defaults() - Get defaults from PPD files and directories.
- #
- sub init_defaults() {
- # Find all PPD files that we could regenerate
- my %found_ppds;
- if (-d $chosen_location) {
- find({wanted => \&find_printers}, $chosen_location);
- foreach (@used_printers) {
- my $tmp;
- $tmp = basename($_);
- chomp ($tmp);
- $tmp =~ s/(^.*)\.ppd.*/$1/;
- $found_ppds{$tmp} = "" if $printers{$tmp};
- }
- }
- @chosen_printers = ();
- foreach (sort keys %found_ppds) {
- push @chosen_printers, $_;
- }
-
- # Find all language directories that could be used
- my %found_langs;
- if (-d $chosen_location) {
- find({wanted => \&find_languages}, $chosen_location);
- foreach (@used_languages) {
- my $tmp;
- $tmp = basename($_);
- chomp ($tmp);
- $found_langs{$tmp} = "" if $languages{$tmp};
- }
- }
- @chosen_languages = ();
- foreach (sort keys %found_langs) {
- push @chosen_languages, $_;
- }
- if (! @chosen_languages) {
- push @chosen_languages, "en";
- }
- }
-
-
- #
- # find-*() - callbacks for File::Find::find().
- #
- sub find_printers {
- my ($dev,$ino,$mode,$nlink,$uid,$gid);
-
- (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
- -f _ &&
- /^.*\.ppd.*\z/s && push @used_printers, $_;
- }
-
- sub find_languages {
- my ($dev,$ino,$mode,$nlink,$uid,$gid);
-
- (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
- -d _ && push @used_languages, $_;
- }
-
-
- # string
- # main_menu() - Display main menu.
- # Return string containing selection.
- #
- sub main_menu() {
- my $option;
- my @menu_options;
- my $menu_desc = << "END";
- Generate Gutenprint PPD files for use with CUPS. This program is a user-friendly interface for cups-genppd(8).
-
- Current PPD directory: $chosen_location
-
- Hint: if the cursor keys cause problems, you may have more luck with +/- and TAB.
- END
- @menu_options = (
- [ "Help", "Display help text" ],
- [ "Directory", "Choose PPD location" ],
- [ "Printers", "Choose printers" ],
- [ "Languages", "Choose languages" ],
- [ "Create", "Create PPDs" ],
- [ "Exit", "Exit the program" ]
- );
- my $dialog_options;
- for my $i ( 0 .. $#menu_options) {
- for my $j ( 0 .. $#{$menu_options[$i]}) {
- $dialog_options .= "\"$menu_options[$i][$j]\" ";
- }
- }
- while (defined($option = dialog_read("cups-genppdconfig", "--no-cancel --default-item Printers --menu \"$menu_desc\" 20 70 6 $dialog_options"))) {
- chomp ($option);
- return $option;
- }
- }
-
-
- #
- # display_help() - Display help text.
- #
- sub display_help {
- my $help_text = <<"END";
- cups-genppdconfig is a program to generate PPD files which enable the
- Gutenprint printer drivers to be used with CUPS, the Common UNIX
- Printing System. A PPD file is a PostScript Printer Description,
- which describes the capabilities of a printer. For each printer model
- that you wish to use, you will have to generate the corresponding PPD
- file.
-
- There are three steps to generating the PPDs:
-
-
- [0. Directory]
-
- The default base directory to create PPD files in is
- /usr/share/cups/model/gutenprint, and this is displayed on the
- main menu. Choose the "Directory" option to change this, but in
- almost every case the default should be used. Don\'t alter the default
- unless you know what you are doing.
-
-
- 1. Printers
-
- Choose the "Printers" menu option. The dialog box shows a complete
- list of all the printers supported by Gutenprint. Use the up and down
- cursor keys to move between the printers and SPACE to select the
- models you want. Next, press ENTER to confirm the selections.
-
- If no printers are chosen, then a PPD file will be created for *every*
- model.
-
-
- 2. Languages
-
- PPD files can be produced in several languages. Choose the
- "Languages" menu option and, as for the "Printers" menu, select the
- languages that you wish to use and press ENTER to confirm the
- selections.
-
- Since a PPD file can only be translated into one language, selecting
- multiple languages is posible, but of limited usefulness (for each
- printer, a separate PPD file for each language will be produced).
-
-
- 3. Save the selections
-
- Choose the "Save" menu option to generate the PPD files you requested.
- The files will be created in the default CUPS data directory
- \$cups_prefix/share/model/gutenprint. Translations will be saved in
- subdirectories named according to the locale/language.
-
-
- Note that unselecting already selected entries in the Printer and
- Language Selection dialogs will *not* remove these from the
- filesystem; it will simply not cause them to be generated when you
- choose "Save". To remove a printer, delete the PPD file from each
- language directory it appears in. To remove a language, delete the
- directory named with the corresponding language code, and all its
- contents.
-
- Once you have finished, choose the "Exit" menu option, to leave the
- program. Note that your selections will be lost, so make sure you
- saved your selections first, if you wanted to keep them.
- END
- my($HELPFILE, $helpfilename) = tempfile("cups-genppdconfig-helpXXXXXX",
- UNLINK => 1)
- or die "can't open temporary help file";
- print $HELPFILE "$help_text";
- $HELPFILE->flush();
- dialog_read("Help", "--textbox $helpfilename 18 76");
- unlink0($HELPFILE, $helpfilename) or die "Error unlinking help file $helpfilename safely: $!";
- close($HELPFILE) or die "can't close help file $helpfilename: $!";
- return;
- }
-
-
- #
- # choose_printers() - Select printers from master list.
- # Default none (so create all printers).
- #
- sub choose_printers {
- my $title = "Printer selection";
- my $options = "--checklist \"Choose the printer models you wish to use with CUPS.\" 18 54 11";
- dialog_read_list(%printers, @chosen_printers, $title, $options);
- }
-
-
- #
- # choose_languages() - Select languages from master list.
- # Default is US English (en).
- #
- sub choose_languages {
- my $title = "Language selection";
- my $options = "--checklist \"Choose the languages you wish to use with CUPS.\" 18 54 11";
- dialog_read_list(%languages, @chosen_languages, $title, $options);
- }
-
-
- #
- # choosen_location() - Select PPD prefix directory and create it if
- # not present.
- #
- sub choose_location {
- my $location;
- $location = dialog_read("Location selection",
- "--inputbox \"Choose a directory to create the PPD files in.\" 8 61 $chosen_location");
- if (!defined($location)) {
- $location = "";
- }
- $chosen_location = create_dir($location); # make sure directory exists
- init_defaults; # use new location to get default selections
- }
-
-
- #
- # create_dir($dir) - Create named directory.
- # $dir will have excess `/'s pruned.
- #
- sub create_dir ($) {
- my $location = $_[0];
- my $dir;
- my $count = 0;
- if ($location =~ m/^\//) {
- $dir = "/";
- }
- foreach (split /\//, $location) {
- if ($_ eq "") {
- next;
- }
- if ($count == 1) {
- $dir .= "/";
- }
- $count = 1;
- $dir .= $_;
- if (!-d $dir) # directory does not exist, so create it
- {
- mkdir $dir || die "can't create directory \`$dir\': $!";
- }
- }
- return $dir;
- }
-
-
- #
- # create_ppds() - Create PPD files.
- #
- sub create_ppds {
- create_dir($chosen_location); # make the destination directory
- my $total = scalar(@chosen_printers);
- my $printers;
- my $count;
- my $language;
- my $percent;
- my $file;
- if (!@chosen_printers) { # calculate total files for guage
- $total = scalar(keys(%printers));
- }
- $total = $total * scalar(@chosen_languages);
- if (@chosen_printers) { # construct printer list for dialog
- foreach (@chosen_printers) {
- $printers .= "$_ ";
- }
- } else {
- $printers = "";
- }
- if (! $silent) {
- open DIALOG, "| $DIALOG --sleep 2 --backtitle \"$BACKTITLE\" --title \"Creating PPD files\" --guage \"Language: \nPPD files: \" 10 72 0"
- or die "can't fork dialog: $!";
- }
- $count = 0;
- foreach $language (@chosen_languages) { # loop through languages
- open GENPPD,
- "LC_ALL=$language LANG=$language LANGUAGE=$language cups-genppd.$version -v -p $chosen_location/$language $printers 2>&1 |"
- or die "can't fork cups-genppd: $!";
- $file = "";
- while ( defined($file = <GENPPD>)) { # dump genppd stats into guage
- chomp($file);
- $count++;
- $percent = int (($count/$total)*100);
- if ($percent > 100) {
- $percent = 100;
- }
- if (! $silent) {
- print DIALOG "$percent\n";
- print DIALOG "XXX\nLanguage: $language\nPPD files: $count/$total\n\n$file\nXXX\n";
- DIALOG->flush();
- } else {
- print "$file\n";
- STDOUT->flush();
- }
- }
- close GENPPD or die "can't close cups-genppd pipe: $!";
- }
- if (! $silent) {
- print DIALOG "100\nXXX\nLanguage: \nPPD files: $total/$total\n\nCompleted\nXXX\n";
- close DIALOG or die "can't close dialog pipe";
- }
- }
-
-
- # scalar
- # dialog($title, $command) - Create a dialog.
- # Returns dialog results.
- sub dialog_read ($$) {
- my($title, $command) = @_;
- my $result = ""; # must not be undefined, just empty
- my $status;
- my $line;
- open DIALOG, "$DIALOG --backtitle \"$BACKTITLE\" --title \"$title\" $command 2>&1 |";
- while (defined($line = <DIALOG>)) {
- $result .= $line;
- }
- close DIALOG or ($! == 0) or die "can't close dialog pipe: $!";
- if ($? >> 8)
- {
- return undef;
- }
- return $result;
- }
-
-
- #
- # dialog_read_list(%masterlist
- # @chosenlist
- # $title
- # $dialog) - Construct list dialog, entries from %masterlist,
- # defaults from @chosenlist.
- #
- sub dialog_read_list (\%\@$$) {
- my $masterlist = $_[0];
- my $list = $_[1];
- my $title = $_[2];
- my $dialogoptions = $_[3];
- my $tmplist;
- my $dialoglist = "";
- my $item;
- my $selected;
- # Make a list for use with dialog.
- foreach $item (sort keys %$masterlist) {
- $selected = "off";
- foreach (@$list) {
- if ($item eq $_) {
- $selected = "on";
- last;
- }
- }
- $dialoglist .= "$item \"$masterlist->{$item}\" $selected ";
- }
- $tmplist = dialog_read("$title", "$dialogoptions $dialoglist");
- if (defined($tmplist)) {
- $tmplist =~ s/\"//g;
- @$list=split(/ /, $tmplist);
- }
- }
-